﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Rotempco.ORM.Generator.Objects;
using Rotempco.ORM.Generator.Logic;
using System.IO;
using Rotempco.ORM.Generator.Enums;

namespace Rotempco.ORM.Generator.Managers
{
    public class ORMManager
    {
        #region [ Singleton Constructor ]

        static readonly ORMManager _Instance = new ORMManager();

        static ORMManager()
        {
        }

        private ORMManager()
        {
        }

        public static ORMManager Instance
        {
            get
            {
                return _Instance;
            }
        }

        #endregion

        public void PerformORM(RotempcoSettings projectSettings, string projectPath, string tableName, string className, string aDALImplementation)
        {
            PerformORM(projectSettings, projectPath, tableName, className, aDALImplementation, ColumnSettingsLogic.GetColumnsWithSettings(projectSettings, tableName));
        }

        public void PerformORM(RotempcoSettings projectSettings, string projectPath, string tableName, string className, string aDALImplementation, List<DatabaseColumn> databaseColumns)
        {
            SetupDirectoryStructure(projectSettings, projectPath);

            CreateFileFromTemplate(projectSettings, projectPath, tableName, className, aDALImplementation, databaseColumns, TemplateEnum.ADALCodebehind);
            CreateFileFromTemplate(projectSettings, projectPath, tableName, className, aDALImplementation, databaseColumns, TemplateEnum.DAL);
            CreateFileFromTemplate(projectSettings, projectPath, tableName, className, aDALImplementation, databaseColumns, TemplateEnum.EntityObject);
            CreateFileFromTemplate(projectSettings, projectPath, tableName, className, aDALImplementation, databaseColumns, TemplateEnum.Factory);
            CreateFileFromTemplate(projectSettings, projectPath, tableName, className, aDALImplementation, databaseColumns, TemplateEnum.DataFactory);
            CreateFileFromTemplate(projectSettings, projectPath, tableName, className, aDALImplementation, databaseColumns, TemplateEnum.PropertyEntityObject);

            //GenerateFactory
            GenerateFactoryFile(projectSettings, projectPath, className,TemplateEnum.Factory);

            //GenerateDataFactory
            GenerateFactoryFile(projectSettings, projectPath, className, TemplateEnum.DataFactory);

            ProjectFileLogic.UpdateProjectsFile(projectSettings, projectPath, className);

            projectSettings.BundleUpdate(() =>
            {
                projectSettings.SetKey("@ADALType_" + tableName, aDALImplementation);

                foreach (DatabaseColumn databaseColumn in databaseColumns)
                {
                    projectSettings.SetKey("@DeletedFlag_" + tableName + "_" + databaseColumn.Name, databaseColumn.DeletedFlag);
                    projectSettings.SetKey("@EncryptedFlag_" + tableName + "_" + databaseColumn.Name, databaseColumn.EncryptionType);
                    projectSettings.SetKey("@EncryptedDataType_" + tableName + "_" + databaseColumn.Name, databaseColumn.EncryptedDataType);
                }
            });
        }
        
        public void SetupDirectoryStructure(RotempcoSettings projectSettings, string projectPath)
        {
            string baseUrl = projectPath + @"\" + projectSettings.GetValue("@ProjectName") + @".BaseClass\";
            if (!Directory.Exists(baseUrl))
                throw new Exception("Project is missing? Could not find directory: " + baseUrl);

            CreateDir(baseUrl + @"DAL");
            CreateDir(baseUrl + @"DAL\Reports");
            CreateDir(baseUrl + @"Logic");
            CreateDir(baseUrl + @"Managers");
            CreateDir(baseUrl + @"Objects");
            CreateDir(baseUrl + @"Objects\EntityObjects");
            CreateDir(baseUrl + @"Objects\EntityObjects\PropertyEntities");
            CreateDir(baseUrl + @"Objects\EntityObjects\ReportObjects");
            CreateDir(baseUrl + @"Objects\Enums");
        }

        private void CreateDir(string path)
        {
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
        }


        private void CreateFileFromTemplate(RotempcoSettings projectSettings, string projectPath, string tableName, string className, string aDALImplementation, List<DatabaseColumn> databaseColumns, TemplateEnum templateEnum)
        {
            string fileContent = TemplateFiller.FillTemplate(projectSettings, templateEnum, tableName, className, aDALImplementation, databaseColumns);
            string filePath = FileNameLogic.GetFilePath(projectSettings, className, templateEnum);

            if ((templateEnum == TemplateEnum.DAL || templateEnum == TemplateEnum.Factory || templateEnum == TemplateEnum.DataFactory) && File.Exists(projectPath + filePath))
                return;

            File.WriteAllText(projectPath + filePath, fileContent);
        }


        private static void GenerateFactoryFile(RotempcoSettings projectSettings, string projectPath, string className, TemplateEnum factoryTemplate)
        {

            string factoryFilePath = FileNameLogic.GetFilePath(projectSettings, className, factoryTemplate);
            string factoryContent = File.ReadAllText(projectPath + factoryFilePath);

            string hest = "public static " + className + "Manager " + className;

            if (factoryContent.Contains("public static " + className + "Manager " + className) ||
                factoryContent.Contains("public static " + className + "Data " + className))
            {
                // Factory element allready existst
            }
            else
            {
                string snippitContent = TemplateFiller.FillFactorySnippit(projectSettings, className);

                int startIndex = factoryContent.Substring(0, factoryContent.LastIndexOf('}')).LastIndexOf('}') - 1;

                factoryContent = factoryContent.Insert(startIndex, snippitContent);

                File.WriteAllText(projectPath + factoryFilePath, factoryContent);
            }
        }

    }
}
